package com.galudisu.handsonic.config;

import com.galudisu.handsonic.base.web.shiro.filter.ForceLogoutFilter;
import com.galudisu.handsonic.base.web.shiro.filter.SecurityConstants;
import com.galudisu.handsonic.base.web.shiro.filter.SysUserFilter;
import org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class WebSecurityFilterConfig extends ShiroWebFilterConfiguration {

    @Bean
    @Override
    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();

        filterFactoryBean.setLoginUrl("/login");
        filterFactoryBean.setSuccessUrl("/home");
        filterFactoryBean.setSecurityManager(securityManager);
        filterFactoryBean.setFilters(filters());
        filterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition().getFilterChainMap());
        return filterFactoryBean;
    }

    @Bean
    protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/logout", "logout");
        chainDefinition.addPathDefinition("/static/favicon.ico", "anon");
        chainDefinition.addPathDefinition("/favicon.ico", "anon");
        chainDefinition.addPathDefinition("/static/**", "anon");
        chainDefinition.addPathDefinition("/captcha", "anon");
        chainDefinition.addPathDefinition("/login", "authc");
        chainDefinition.addPathDefinition("/authenticated", "authc");
        chainDefinition.addPathDefinition("/**", "forceLogout,user,sysUser");
        return chainDefinition;
    }

    private Map<String, Filter> filters() {
        Map<String, Filter> filters = new HashMap<>();
        filters.put("authc", formAuthenticationFilter());
        filters.put("sysUser", sysUserFilter());
        filters.put("forceLogout", forceLogoutFilter());
        return filters;
    }

    @Bean(name = "filterShiroFilterRegistrationBean")
    protected FilterRegistrationBean filterShiroFilterRegistrationBean() throws Exception {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter((AbstractShiroFilter) shiroFilterFactoryBean().getObject());
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }

    FormAuthenticationFilter formAuthenticationFilter() {
        FormAuthenticationFilter formFilter = new FormAuthenticationFilter();
        formFilter.setUsernameParam("username");
        formFilter.setPasswordParam("password");
        formFilter.setRememberMeParam("rememberMe");
        formFilter.setLoginUrl("/login");
        return formFilter;
    }

    SysUserFilter sysUserFilter() {
        return new SysUserFilter();
    }

    ForceLogoutFilter forceLogoutFilter() {
        return new ForceLogoutFilter();
    }
}
